<template>
  <div v-if="!fail" class="code-content">
    <div class="header">
      <div class="header-title">
        <div class="elliptical-1 code-name"></div>
        <div class="code-line"></div>
        <div class="code-size"></div>
      </div>
      <div class="header-down">
        <a-button type="text" class="icon-only-btn button-padding" @click.stop="handleToDownload(propValue?.sourceUrl)">
          <i class="iconfont icon-download-2-line"></i><span>下载源码</span>
        </a-button>
      </div>
    </div>
    <div class="main">
      <div class="main-left">
        <code-tree
          :tree-data="(propValue?.fileTree?.childList as any[])"
          :default-path="(propValue?.fileTree?.defultPath as string)"
          @on-select="handleToSelect"
        />
      </div>
      <div class="code-and-res">
        <code-editor v-if="hasCode" ref="codeEditorRef" class="code-editor" :text-value="codeEditorValue" :is-dark-mode="false" />
        <default-graph v-else :show-img="false">
          <template #title>
            <h4 class="default-graph-title">无可展示代码</h4>
          </template>
        </default-graph>
      </div>
    </div>
  </div>
  <default-graph v-else>
    <img src="@/assets/img/error.svg" alt="加载失败" />
  </default-graph>
</template>

<script lang="ts" setup>
  import { debounce, downloadFile } from 'g6-fn'
  import { nextTick, onMounted, ref } from 'vue'
  import { useRequest } from 'vue-request'

  import CodeEditor from '@/components/CodeEditor/index.vue'
  import CodeTree from '@/components/CodeTree/index.vue'
  import { minioApi, modelLibraryApi } from '@/services/api'
  import { waitLoading } from '@/utils'

  import { DetailType } from '../../types'

  export interface Props {
    propValue?: DetailType
  }
  const props = withDefaults(defineProps<Props>(), {})
  const codeEditorValue = ref('') //编辑器当前内容
  const codeEditorRef = ref()

  const hasCode = ref(true) //是否有代码

  const fail = ref(false)
  const { runAsync: getFileContentData } = useRequest<any>((path: string) => modelLibraryApi.getFileContent(path)(), {
    onSuccess: ({ data }) => {
      codeEditorRef.value.setValue(data)
    },
    onError: (error: any) => {
      if (error?.code === 'MODEL-500018') {
        fail.value = true
      }
    }
  })

  //下载
  const handleToDownload = debounce(async (dataUrl: string): Promise<void> => {
    const res = await waitLoading<ResponseData<any>>(minioApi.download({ fileName: dataUrl }), {
      loadingText: '数据准备中,请耐心等待...',
      errorText: '文件下载失败'
    })
    downloadFile(res?.data, dataUrl)
  }, 500)

  const handleToSelect = (key: string[], e: any) => {
    const postfix: string = e.node.name.split('.')?.slice(-1)[0]
    if (postfix === 'py' && key.length) {
      const eCode = encodeURIComponent(key.toString())
      getFileContentData(eCode)
    }
  }

  onMounted(async () => {
    await nextTick()
    codeEditorRef.value?.setReadOnly(true)
    // 没有默认代码说明代码书没有可用代码
    if (!props.propValue?.fileTree?.defultPath) {
      hasCode.value = false
      return
    }
    getFileContentData(encodeURIComponent(props.propValue?.fileTree?.defultPath as string))
  })
</script>

<style lang="less" scoped>
  .code-content {
    display: flex;
    align-items: flex-start;
    overflow: hidden;
    width: 100%;
    background: #fff;
    border: 1px solid #e8e9eb;
    border-radius: 10px;
    flex-direction: column;

    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 10px 24px;
      width: 100%;
      flex-direction: row;
      border-bottom: 1px solid rgba(0, 0, 0, 0.05);

      .header-title {
        display: flex;
        flex-direction: row;
        gap: 24px;

        .code-line {
          width: 1px;
          background: #d9d9db;
        }

        .code-size {
          color: rgba(17, 22, 31, 0.5);
        }

        .code-name {
          max-width: 300px;
        }
      }

      .header-down {
        .button-padding {
          padding: 7px 16px;
          gap: 6px;
          color: #1868e9;
        }
      }
    }

    .main {
      display: flex;
      overflow: hidden;
      width: 100%;
      height: 100%;
      height: 611px;

      .main-left {
        overflow: auto;
        width: 320px;
        max-width: 320px;
        height: 570px;
        min-height: 460px;
        background-color: #fff;
        border-right: 1px solid rgba(0, 0, 0, 0.05);
      }

      .code-and-res {
        flex: 1;
        // min-height: 400px;
        // border: 1px solid orange;

        .code-editor {
          height: 100%;
        }
      }
    }

    .default-graph-title {
      font-size: 14px;
      text-align: center;
      color: rgba(17, 22, 31, 0.52);
      font-weight: 400;
      line-height: 22px;
    }
  }
</style>
